#!/usr/bin/env python3
"""
基于JSON结构模式的解密尝试
"""

from collections import Counter, defaultdict
import json

def load_decoded_data():
    """加载Base64解码后的数据"""
    with open('decoded_result.bin', 'rb') as f:
        return f.read()

def analyze_json_patterns():
    """基于JSON结构分析加密模式"""
    print("🎯 === 基于JSON结构的解密 ===\n")
    
    data = load_decoded_data()
    
    # JSON中常见的字节模式
    # ": 引号+冒号
    # ", 引号+逗号
    # ": " 引号+冒号+空格
    # "} 引号+右大括号
    # {" 左大括号+引号
    
    # 1. 找出最频繁的字节（可能是引号）
    byte_freq = Counter(data)
    most_frequent = byte_freq.most_common(10)
    
    print("最频繁的字节:")
    for byte_val, count in most_frequent[:5]:
        print(f"  0x{byte_val:02x}: {count}次")
    
    quote_candidate = most_frequent[0][0]  # 0x69
    print(f"\n假设 0x{quote_candidate:02x} = '\"' (引号)")
    
    # 2. 分析引号后面的字节
    after_quote = defaultdict(int)
    before_quote = defaultdict(int)
    
    for i in range(1, len(data)-1):
        if data[i] == quote_candidate:
            after_quote[data[i+1]] += 1
            before_quote[data[i-1]] += 1
    
    print(f"\n引号后面最常见的字节:")
    after_sorted = sorted(after_quote.items(), key=lambda x: x[1], reverse=True)
    for byte_val, count in after_sorted[:5]:
        print(f"  0x{byte_val:02x}: {count}次")
    
    # 引号后面最常见的应该是冒号或逗号
    colon_candidate = after_sorted[0][0]  # 可能是冒号
    comma_candidate = after_sorted[1][0]  # 可能是逗号
    
    print(f"\n假设 0x{colon_candidate:02x} = ':' (冒号)")
    print(f"假设 0x{comma_candidate:02x} = ',' (逗号)")
    
    # 3. 查找可能的大括号
    # 第一个和最后一个字节可能是大括号
    open_brace_candidate = data[0]
    close_brace_candidate = data[-1]
    
    print(f"\n假设 0x{open_brace_candidate:02x} = '{{' (开始大括号)")
    print(f"假设 0x{close_brace_candidate:02x} = '}}' (结束大括号)")
    
    # 4. 查找空格（在冒号后面常见）
    after_colon = defaultdict(int)
    for i in range(len(data)-1):
        if data[i] == colon_candidate:
            after_colon[data[i+1]] += 1
    
    space_candidate = sorted(after_colon.items(), key=lambda x: x[1], reverse=True)[0][0]
    print(f"\n假设 0x{space_candidate:02x} = ' ' (空格)")
    
    # 5. 构建初步映射表
    mapping = {
        quote_candidate: ord('"'),
        colon_candidate: ord(':'),
        comma_candidate: ord(','),
        open_brace_candidate: ord('{'),
        close_brace_candidate: ord('}'),
        space_candidate: ord(' ')
    }
    
    # 6. 查找可能的字段名
    # 在JSON中，字段名通常是 "xxx": 的模式
    print("\n\n查找可能的字段名模式:")
    
    # 查找 引号...引号冒号 的模式
    field_patterns = []
    i = 0
    while i < len(data) - 3:
        if data[i] == quote_candidate:
            # 找下一个引号
            j = i + 1
            while j < len(data) and data[j] != quote_candidate:
                j += 1
            
            if j < len(data) - 1 and data[j+1] == colon_candidate:
                # 找到一个字段名
                field = data[i:j+1]
                field_patterns.append(field)
                i = j + 1
            else:
                i += 1
        else:
            i += 1
    
    # 统计字段模式
    field_counter = Counter(field_patterns)
    print(f"找到 {len(field_counter)} 个不同的字段模式")
    
    common_fields = field_counter.most_common(10)
    print("\n最常见的字段模式:")
    for field, count in common_fields:
        hex_field = field.hex()
        print(f"  {hex_field}: {count}次")
    
    # 7. 尝试匹配已知的字段名
    known_fields = [b"questionText", b"conversationId", b"userId", b"sessionId", b"model"]
    
    print("\n\n尝试匹配已知字段名:")
    for known in known_fields:
        # 构建期望的加密模式
        expected_pattern = bytes([quote_candidate]) + known + bytes([quote_candidate])
        expected_len = len(expected_pattern)
        
        # 查找长度匹配的字段
        matches = []
        for field, count in common_fields:
            if len(field) == expected_len:
                matches.append((field, count))
        
        if matches:
            print(f"\n'{known.decode()}' (长度{expected_len}) 可能匹配:")
            for field, count in matches[:3]:
                print(f"  {field.hex()} ({count}次)")
                
                # 尝试创建映射
                if len(field) == len(expected_pattern):
                    for i in range(1, len(field)-1):  # 跳过引号
                        if field[i] not in mapping:
                            mapping[field[i]] = expected_pattern[i]
    
    # 8. 应用映射解密
    print("\n\n应用映射表解密:")
    print(f"当前映射表包含 {len(mapping)} 个字符")
    
    decrypted = bytearray()
    unmapped_count = 0
    
    for byte in data:
        if byte in mapping:
            decrypted.append(mapping[byte])
        else:
            decrypted.append(byte)
            unmapped_count += 1
    
    print(f"未映射的字节: {unmapped_count}/{len(data)}")
    
    # 保存部分解密结果
    with open('partial_decrypt.bin', 'wb') as f:
        f.write(decrypted)
    
    print("\n部分解密结果已保存到 partial_decrypt.bin")
    print(f"前200字节预览: {bytes(decrypted[:200])}")
    
    # 9. 尝试进一步改进映射
    improve_mapping(data, mapping, decrypted)
    
    return mapping

def improve_mapping(data, mapping, partial_decrypt):
    """改进映射表"""
    print("\n\n🔧 === 改进映射表 ===")
    
    # 查找部分解密中的可识别模式
    # 例如 "xxx": 后面通常是值
    
    # 统计未映射字节的上下文
    unmapped_contexts = defaultdict(list)
    
    for i in range(1, len(data)-1):
        if data[i] not in mapping:
            # 记录前后字节
            prev_char = mapping.get(data[i-1], '?')
            next_char = mapping.get(data[i+1], '?')
            
            if isinstance(prev_char, int):
                prev_char = chr(prev_char) if 32 <= prev_char <= 126 else '?'
            if isinstance(next_char, int):
                next_char = chr(next_char) if 32 <= next_char <= 126 else '?'
            
            context = f"{prev_char}_{next_char}"
            unmapped_contexts[data[i]].append(context)
    
    print("未映射字节的常见上下文:")
    for byte_val, contexts in sorted(unmapped_contexts.items(), key=lambda x: len(x[1]), reverse=True)[:10]:
        context_freq = Counter(contexts)
        most_common_context = context_freq.most_common(1)[0]
        print(f"  0x{byte_val:02x}: {most_common_context[0]} ({most_common_context[1]}次)")
        
        # 基于上下文猜测字符
        context_str = most_common_context[0]
        if context_str == '":_"':
            print(f"    可能是值的开始，如数字或字母")
        elif context_str == '"_"':
            print(f"    在两个引号之间，可能是字段名的一部分")

def final_decrypt_attempt():
    """最终解密尝试"""
    mapping = analyze_json_patterns()
    
    print("\n\n🎯 === 最终解密尝试 ===")
    
    # 加载部分解密的数据
    with open('partial_decrypt.bin', 'rb') as f:
        partial = f.read()
    
    # 查找可识别的JSON结构
    printable_ratio = sum(1 for b in partial if 32 <= b <= 126) / len(partial)
    print(f"可打印字符比例: {printable_ratio*100:.1f}%")
    
    # 尝试将部分解密结果作为文本查看
    try:
        text = partial.decode('utf-8', errors='ignore')
        print(f"\n尝试UTF-8解码 (前500字符):")
        print(text[:500])
    except:
        pass
    
    # 检查是否包含JSON特征
    json_features = [b'{"', b'"}', b'": ', b'", "', b'"questionText"']
    found_features = []
    
    for feature in json_features:
        if feature in partial:
            found_features.append(feature.decode())
    
    if found_features:
        print(f"\n找到JSON特征: {found_features}")
        print("✅ 解密可能成功!")
        
        # 尝试提取完整的JSON
        try:
            # 找到第一个 { 和最后一个 }
            start = partial.find(b'{')
            end = partial.rfind(b'}')
            
            if start >= 0 and end > start:
                json_candidate = partial[start:end+1]
                
                # 尝试解析
                try:
                    # 替换未映射的字节为占位符
                    cleaned = bytearray()
                    for b in json_candidate:
                        if 32 <= b <= 126:
                            cleaned.append(b)
                        else:
                            cleaned.append(ord('?'))
                    
                    print(f"\n提取的JSON候选 (前500字符):")
                    print(bytes(cleaned).decode('utf-8', errors='ignore')[:500])
                    
                    with open('extracted_json.txt', 'wb') as f:
                        f.write(cleaned)
                    print("\n已保存到 extracted_json.txt")
                except:
                    pass
        except:
            pass
    else:
        print("\n❌ 未找到明显的JSON特征，需要更多分析")

if __name__ == "__main__":
    final_decrypt_attempt()
    
    print("\n\n💡 === 结论 ===")
    print("这是一个复杂的字节替换密码")
    print("已经识别了部分字符映射")
    print("需要：")
    print("1. 更多的已知明文来完善映射表")
    print("2. 或通过动态调试获取完整的替换表")
    print("3. 检查extracted_json.txt和partial_decrypt.bin查看进展")